package com.luoyx.vjsb.common.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;

/**
 * <p>
 * 控制台输出日志
 * </p>
 *
 * @author luoyuanxiang <p>luoyuanxiang.github.io</p>
 * @since 2020/4/7 14:36
 */
@Slf4j
@Aspect
@Component
public class ConsoleLogsAspect {

    /**
     * 切入点
     */
    @Pointcut("execution(* com.luoyx.vjsb.*.controller.*.*(..))")
    public void point() {}


    /**
     * 前置通知
     * @param joinPoint 1
     */
    @Before("point()")
    public void before(JoinPoint joinPoint) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert attributes != null;
        HttpServletRequest request = attributes.getRequest();
        // 打印请求相关参数
        log.info("========================================== Start ==========================================");
        // 打印请求 url
        log.info("请求路径    : {}", request.getRequestURL().toString());
        // 打印 Http method
        log.info("请求方法    : {}", request.getMethod());
        // 打印调用 controller 的全路径以及执行方法
        log.info("请求的类    : {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
        // 打印请求的 IP
        log.info("请求IP      : {}", request.getRemoteAddr());
        log.info("请求参数    : {}", Arrays.toString(joinPoint.getArgs()));
    }

    /**
     * 环绕通知
     * @param pjp 1
     * @return 1
     */
    @Around("point()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object result = pjp.proceed();
        log.info("执行时间     : {}ms", (System.currentTimeMillis() - startTime));
        return result;
    }

    /**
     * 异常通知:在方法抛出异常退出时执行的通知。
     * @param joinPoint 1
     * @param ex 1
     */
    @AfterThrowing(value = "point()", throwing = "ex")
    public void afterThrowing(JoinPoint joinPoint, Throwable ex) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert attributes != null;
        HttpServletRequest request = attributes.getRequest();
        String logTemplate = "--------------- 执行失败 ---------------\n异常请求开始---Send Request URL: {}, Method: {}, Params: {} \n异常请求方法---ClassName: {}, [Method]: {}, \n异常请求结束---Exception Message: {}";
        log.error(logTemplate, request.getRequestURL(), request.getMethod(),  joinPoint.getArgs() != null ? Arrays.toString(joinPoint.getArgs()) : null, joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName(), ex.getMessage());
    }

    /**
     * 后置通知
     */
    @After("point()")
    public void after() {
        log.info("=========================================== End ===========================================");
        // 每个请求之间空一行
        log.info("");
    }
}
